﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

public class CreateAssetBundles : EditorWindow
{
    private static Dictionary<string, string> dicArgs;

    [MenuItem("Build/Build AssetBundle")]
    public static void BuildAssetBundleWindow()
    {
        BuildAssetBundles(BuildTarget.StandaloneWindows);
    }

    public static void BuildAssetBundles(BuildTarget buildTarget)
    {
        string p = Application.dataPath + "/StreamingAssets/AssetBundle";
        if (Directory.Exists(p) == true)
            Directory.Delete(p, true);
        Directory.CreateDirectory(p);

        CreateBundle();

        BuildPipeline.BuildAssetBundles(p, BuildAssetBundleOptions.ChunkBasedCompression, buildTarget);

        CreateAssetslist();

        Debug.Log("BuildAssetBundles End");
    }

    public static void CreateBundle()
    {
        ClearAll();

        string path = "Assets/AssetBundlesLocal";

        string[] allDir = Directory.GetDirectories(path);
        Debug.Log(" allDir.Length   " + allDir.Length);
        for (int i = 0; i < allDir.Length; i++)
        {
            string[] allFiles = Directory.GetFiles(allDir[i]);
            string dirName = Path.GetFileName(allDir[i]);
            Debug.Log("dirName   " + dirName);

            for (int j = 0; j < allFiles.Length; j++)
            {
                Debug.Log("allFiles[j]  " + allFiles[j]);
                EditorUtility.DisplayProgressBar(dirName, allFiles[j], (1f + j) / allFiles.Length);
                if (Path.GetExtension(allFiles[j]) == ".meta")
                    continue;
                AssetImporter importer = AssetImporter.GetAtPath(allFiles[j]);
                if (importer != null)
                    importer.assetBundleName = dirName.ToLower();
            }

        }
        CreateLuaBundle();
        CreateSpriteBundle();
        CreateMoudleBundle();
        CreatePrefabBundle();
        EditorUtility.ClearProgressBar();

        AssetDatabase.Refresh();
    }

    public static void CreateLuaBundle()
    {
        string path = "Assets/Lua";
        EditorUtility.DisplayProgressBar("CreateLuaBundle", "wait", 0);
        AssetImporter importer = AssetImporter.GetAtPath(path);
        Debug.Log("importer " + importer);
        importer.assetBundleName = "lua";
    }
    private static void CreateMoudleBundle()
    {
        string path = "Assets/AssetBundlesLocal/Module";

        string[] allDir = Directory.GetDirectories(path);
        for (int i = 0; i < allDir.Length; i++)
        {
            string[] allFiles = Directory.GetFiles(allDir[i]);
            string dirName = Path.GetFileName(allDir[i]);

            for (int j = 0; j < allFiles.Length; j++)
            {
                EditorUtility.DisplayProgressBar("Module " + dirName, allFiles[j], (1f + j) / allFiles.Length);
                if (Path.GetExtension(allFiles[j]) == ".meta")
                    continue;
                AssetImporter importer = AssetImporter.GetAtPath(allFiles[j]);
                if (importer != null)
                    importer.assetBundleName = dirName.ToLower();
            }

        }
    }
    private static void CreateSpriteBundle()
    {
        string path = "Assets/AssetBundlesLocal/Sprite";

        string[] allDir = Directory.GetDirectories(path);
        for (int i = 0; i < allDir.Length; i++)
        {
            string[] allFiles = Directory.GetFiles(allDir[i]);
            string dirName = Path.GetFileName(allDir[i]);

            for (int j = 0; j < allFiles.Length; j++)
            {
                EditorUtility.DisplayProgressBar("Sprite " + dirName, allFiles[j], (1f + j) / allFiles.Length);
                if (Path.GetExtension(allFiles[j]) == ".meta")
                    continue;
                AssetImporter importer = AssetImporter.GetAtPath(allFiles[j]);
                if (importer != null)
                    importer.assetBundleName = dirName.ToLower();
            }

        }
    }
    private static void CreatePrefabBundle()
    {
        string path = "Assets/AssetBundlesLocal/Prefab";

        string[] allDir = Directory.GetDirectories(path);
        for (int i = 0; i < allDir.Length; i++)
        {
            string[] allFiles = Directory.GetFiles(allDir[i]);
            string dirName = Path.GetFileName(allDir[i]);

            for (int j = 0; j < allFiles.Length; j++)
            {
                EditorUtility.DisplayProgressBar("Prefab " + dirName, allFiles[j], (1f + j) / allFiles.Length);
                if (Path.GetExtension(allFiles[j]) == ".meta")
                    continue;
                AssetImporter importer = AssetImporter.GetAtPath(allFiles[j]);
                if (importer != null)
                    importer.assetBundleName = dirName.ToLower();
            }

        }
    }
    private static void CreateAssetslist()
    {
        string txtInfo = GetCurrentTimeUnix().ToString();
        string path = Application.dataPath + "/StreamingAssets/AssetBundle";
        string[] arrFiles = Directory.GetFiles(path);

        string type = "";

        if (dicArgs != null && dicArgs.ContainsKey("BundleType") == true)
        {
            type = dicArgs["BundleType"];
        }

        for (int i = 0; i < arrFiles.Length; i++)
        {
            EditorUtility.DisplayProgressBar("BuildAssetBundles", arrFiles[i], 1f * (1 + i) / arrFiles.Length);

            string fileName = Path.GetFileNameWithoutExtension(arrFiles[i]);
            string extension = Path.GetExtension(arrFiles[i]);
            if (extension == ".manifest")
            {
                File.Delete(arrFiles[i]);
                continue;
            }

            FileStream file = new FileStream(arrFiles[i], FileMode.Open);
            string md5 = GetMD5HashFromFile(file);
            string info = "0," + fileName + "," + md5 + "," + file.Length;
            file.Close();

            txtInfo += "\n" + info;

            File.Move(arrFiles[i], Path.Combine(path, fileName + "_" + md5 + extension));
        }

        EditorUtility.ClearProgressBar();

        File.WriteAllText(Application.dataPath + "/StreamingAssets/AssetBundle/assetslist.txt", txtInfo);
    }

    public static void ClearAll()
    {
        string[] allFiles = AssetDatabase.GetAllAssetPaths();
        Debug.Log(" allFiles.Length " + allFiles.Length);
        for (int i = 0; i < allFiles.Length; i++)
        {
            EditorUtility.DisplayProgressBar("clear bundler", allFiles[i], (1f + i) / allFiles.Length);

            string fileExtension = Path.GetExtension(allFiles[i]);
            if (fileExtension == ".cs" || fileExtension == ".js")
                continue;
            Debug.Log(" fileExtension   " + fileExtension);
            AssetImporter importer = AssetImporter.GetAtPath(allFiles[i]);
            if (importer != null)

                importer.assetBundleName = "";
        }
        EditorUtility.ClearProgressBar();
    }

    private static long GetCurrentTimeUnix()
    {
        TimeSpan cha = (DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)));
        long t = (long)cha.TotalSeconds;
        return t;
    }

    private static string GetMD5HashFromFile(FileStream file)
    {
        try
        {
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(file);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }
        catch (Exception ex)
        {
            throw new Exception("GetMD5HashFromFile() fail, error:" + ex.Message);
        }
    }

    public static void GetAllFiles(string path, List<string> listName)
    {
        string[] files = Directory.GetFiles(path);
        listName.AddRange(files);

        string[] dirs = Directory.GetDirectories(path);
        for (int i = 0; i < dirs.Length; i++)
        {
            GetAllFiles(dirs[i], listName);
        }
    }
}